package com.itheima.tliasmanagementspringboot.config;

import com.itheima.tliasmanagementspringboot.service.EmpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@Configuration
public class JDKProxyUtils {
    //JDK实现动态代理

    //原因是创建目标/原始代理对象时，需要传入原始对象(目标对象）,方法的三个参数,前两个都和原始对象有关
    //此处注入的目的是将IOC容器中原始对象传入
    @Autowired
    EmpService empService;

    //Bean注解一般配合@Configuration注解使用
    @Bean //将方法的返回值放入IOC容器，方法名就是对象的名称,
    public EmpService empService() {
        //1. 目标对象 empService

        //2. 目标对象创建代理对象,JDK实现动态代理
        //代理只是和实现类实现了相同的接口,二者没有并没有直接的联系
                //参数1：用于指定一个类加载器
                //参数2：指定生成的代理长什么样子，也就是有哪些方法
                //参数3：用来指定生成的代理对象要干什么事情
        EmpService proxy = (EmpService)Proxy.newProxyInstance(empService.getClass().getClassLoader(), empService.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("JDK动态代理实现AOP,前置: ");

                Object invoke = method.invoke(empService, args);

                System.out.println("JDK动态代理实现AOP,后置: ");
                //此处注入的目的是将目标对象的代理放入IOC容器中
                return invoke;//此处返回的是原始方法的返回值,也可以自己写的逻辑处理后的数据,这样和原始方法区别就很大了
            }
        });
        //返回代理对象，将代理对象放入IOC容器
        return proxy;//返回动态代理对象
    }
}
